/*
 * Galaxium Messenger
 * Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Text;

using GLib;
using Gdk;
using Gtk;

using Anculus.Core;

using Galaxium.Core;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;

namespace Galaxium.Protocol.GaduGadu.GtkGui
{
	public class GaduContactTreeManager : BasicContactTreeManager
	{
		public override void RenderText (object data, CellRendererContact renderer)
		{
			if (!(data is GaduContact))
			{
				base.RenderText (data, renderer);
				return;
			}
			
			GaduContact contact = data as GaduContact;
			StringBuilder sb = new StringBuilder ();
			ContactTreeDetailLevel detail = contact.Session.Account.DetailLevel;
			
			sb.Append (Markup.EscapeText (contact.DisplayIdentifier));
			
			if (detail != ContactTreeDetailLevel.Compact)
			{
				if (detail == ContactTreeDetailLevel.Detailed)
					sb.AppendFormat ("\n<span size=\"small\">{0}</span>\n", Markup.EscapeText (contact.UniqueIdentifier));
				
				sb.AppendFormat ("\n<span foreground=\"#505050\" weight=\"light\"><i>({0})</i></span>\n", contact.Presence.State);
			}
			else
				sb.AppendFormat (" <span foreground=\"#505050\" weight=\"light\"><i>({0})</i></span>\n", contact.Presence.State);
			
			renderer.Markup = sb.ToString ();
		}
		
		public override void RenderLeftImage (object data, CellRendererPixbuf renderer)
		{
			if (!(data is GaduContact))
			{
				base.RenderLeftImage (data, renderer);
				return;
			}
			
			GaduContact contact = data as GaduContact;
			ContactTreeDetailLevel detailLevel = contact.Session.Account.DetailLevel;
			IIconSize iconSize = IconSizes.Other;
			Pixbuf pixbuf = null;
			
			switch (detailLevel)
			{
			case ContactTreeDetailLevel.Compact:
				iconSize = IconSizes.Small;
				break;
				
			case ContactTreeDetailLevel.Normal:
				iconSize = IconSizes.Medium;
				break;
				
			case ContactTreeDetailLevel.Detailed:
				iconSize = IconSizes.Large;
				break;
				
			default:
				// not currently dealign with this size.
				break;
			}
			
			// If the detail level is compact, we dont overlay, we just display the overlay itself. 
			if (detailLevel == ContactTreeDetailLevel.Compact)
			{
				if (contact.Presence == GaduPresence.Offline)
					pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
				else if (contact.Presence == GaduPresence.Away)
					pixbuf = IconUtility.GetIcon ("galaxium-status-away", iconSize);
				else if (contact.Presence == GaduPresence.Online)
					pixbuf = IconUtility.GetIcon ("galaxium-online", iconSize);
			}
			else
			{
				if (contact.DisplayImage != null && contact.DisplayImage.ImageBuffer != null && contact.Session.Account.ShowDisplayImages && !contact.SupressImage)
				{
					try
					{
						if (contact.Presence == GaduPresence.Offline)
							pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
						else
							pixbuf = PixbufUtility.GetFramedPixbuf (new Gdk.Pixbuf(contact.DisplayImage.ImageBuffer), detailLevel);
					}
					catch
					{
						Anculus.Core.Log.Debug ("Unable to generate an image from the data in the image buffer ["+contact.DisplayImage.ImageBuffer.Length+"] for: "+contact.UniqueIdentifier);
						if (contact.Presence == GaduPresence.Offline)
							pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
						else
							pixbuf = IconUtility.GetIcon ("galaxium-online", iconSize);
					}
				}
				else
				{
					if (contact.Presence == GaduPresence.Offline)
						pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
					else
						pixbuf = IconUtility.GetIcon ("galaxium-online", iconSize);
				}
				
				// We are not in compact mode, so we need to use overlays now.
				if (contact.Presence == GaduPresence.Away)
					pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-away", IconSizes.Small));
			}
			
			renderer.Pixbuf = pixbuf;
			renderer.Width = pixbuf.Width;
			renderer.Visible = true;
		}
		
		public override string GetMenuExtensionPoint (object data)
		{
			// This is done to force the use of XMPP instead of GOOGLE
			//TODO: allow this some other way
			
			if (data is IContact)
				return "/Galaxium/Gui/GG/ContactTree/ContextMenu/Contact";
			if (data is ContactTreeRealGroup)
				return "/Galaxium/Gui/GG/ContactTree/ContextMenu/Group";
			
			return base.GetMenuExtensionPoint (data);
		}
				
		public override InfoTooltip GetTooltip (object data)
		{
			if (data is GaduContact)
				return new ContactListTooltip (data as GaduContact);
			
			return base.GetTooltip (data);
		}
		
		public override int Compare (object data1, object data2)
		{
			GaduContact contact1 = data1 as GaduContact;
			
			if ((contact1 != null) && (!contact1.Session.Account.SortAlphabetic))
			{
				GaduContact contact2 = data2 as GaduContact;
				
				int ret = GetPresenceValue (contact1.Presence).CompareTo (GetPresenceValue (contact2.Presence));
				
				if (ret != 0)
					return ret;
			}
			
			return base.Compare (data1, data2);
		}
		
		private int GetPresenceValue (IPresence presence)
		{
			//TODO: Where do the other GaduPresence.* values fit in here?
			
			if (presence == GaduPresence.Online)
				return 0;
			else if (presence == GaduPresence.Idle)
				return 1;
			else if (presence == GaduPresence.Busy)
				return 2;
			else if (presence == GaduPresence.Away)
				return 3;
			else if (presence == GaduPresence.Invisible)
				return 4;
			else
				return 5;
		}
	}
}
